﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Atlepage.Syntactic
{
    class LRItemSet : List<LRItem>
    {
        static int lastid = -1;
        int id;
        string cachedString;
        Dictionary<ProductionNode, LRItemSet> transitions = new Dictionary<ProductionNode, LRItemSet>();

        public LRItemSet()
        {
            id = ++lastid;
        }

        public new void Add(LRItem item)
        {
            if (base.Contains(item))
                return;
            base.Add(item);
        }

        public new void AddRange(IEnumerable<LRItem> items)
        {
            foreach (var item in items)
            {
                this.Add(item);
            }
        }

        public override string ToString()
        {
            if (cachedString == null)
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("{");
                sb.Append(id);
                sb.Append("| ");
                for (int i = 0; i < Count; i++)
                {
                    if (i > 0) sb.Append(", ");
                    sb.Append(base[i]);
                }
                foreach (var item in transitions)
                {
                    sb.Append(", ");
                    sb.Append(item.Key);
                    sb.Append(" -> ");
                    sb.Append(item.Value.id);
                }
                sb.Append("}");
                cachedString = sb.ToString();
            }
            return cachedString;
        }

        public LRItem Kernel { get { return this[0]; } }

        internal void AddTransition(ProductionNode productionNode, LRItemSet childSet)
        {
            cachedString = null;
            transitions.Add(productionNode, childSet);
        }

        public IEnumerable<KeyValuePair<ProductionNode, LRItemSet>> Transitions
        {
            get
            {
                foreach (var item in transitions)
                {
                    yield return item;
                }
            }
        }
    }
}
